#pragma once

#include <inttypes.h>
#include <stdlib.h>

#include <vector>
#include <cstring>
#include <assert.h>

// template functions to serialize plain of data types into byte array
template <typename PODType>
void TSerialize(std::vector<uint8_t>& byteArray, const PODType& data)
{
	assert(std::is_pod<PODType>::value);
	size_t oldSize = byteArray.size();
	byteArray.resize(oldSize + sizeof(data));
	std::memcpy(&byteArray[oldSize], &data, sizeof(data));
}

void TSerialize(std::vector<uint8_t>& byteArray, bool data);

template <typename PODType >
void TSerialize(std::vector<uint8_t>& byteArray, const std::vector<PODType>& data)
{
	assert(std::is_pod<PODType>::value);
	uint64_t arraySize = (uint64_t)data.size();
	TSerialize(byteArray, arraySize);
	if (arraySize > 0) {
		size_t dataSize = arraySize * sizeof(PODType);
		size_t oldSize = byteArray.size();
		byteArray.resize(oldSize + dataSize);
		std::memcpy(&byteArray[oldSize], &data.front(), dataSize);
	}
}


// template functions to serialize plain of data types into byte array
template <typename PODType>
size_t TDeserialize(void* pSrc, PODType& data)
{
	assert(std::is_pod<PODType>::value);
	PODType* pData = (PODType*)pSrc;
	data = *pData;

	return sizeof(PODType);
}

size_t TDeserialize(void* pSrc, bool& data);

template <typename PODType >
size_t TDeserialize(void* pSrc, std::vector<PODType>& data)
{
	assert(std::is_pod<PODType>::value);
	uint64_t arraySize = 0;
	uint8_t* pByte = (uint8_t*)pSrc;
	pByte += TDeserialize(pByte, arraySize);
	if (arraySize > 0) {
		size_t dataSize = arraySize * sizeof(PODType);
		size_t oldSize = data.size();
		data.resize(oldSize + arraySize);
		std::memcpy(&data[oldSize], pByte, dataSize);
		return sizeof(uint64_t) + dataSize;
	}
	else
		return sizeof(uint64_t);
}
